#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <wait.h>
#include <string.h>
#include <errno.h>
#include "network.h"
#include "debug_printf.h"


static void doInit(Socket *s);
static int doGetMessage(Socket *s);

Socket *makeSocket(void) {
	Socket *s = (Socket*) malloc(sizeof(Socket));

	s->init = doInit;
	s->getMessage = doGetMessage;
	return s;
}

static void doInit(Socket *this) {

	int count;
	int opt = 1;
	this->maxClients = 3;

	for(count = 0; count < this->maxClients; count++)
		this->sockClient[count] = 0;

	this->sockMaster =  socket(AF_INET, SOCK_STREAM, 0);
	if(!this->sockMaster) {
		perror("Error createing socket\n");
		this->status = -1;
		return;
	}

    if (setsockopt(this->sockMaster, SOL_SOCKET, SO_REUSEADDR, 
                 (char *)&opt, sizeof(opt))<0) {
		perror("setsockopt");
		this->status = -2;
		return;
	}

	this->addr.sin_family = AF_INET;
	this->addr.sin_addr.s_addr = INADDR_ANY;
	this->addr.sin_port = htons(7000);
	if (bind(this->sockMaster, (struct sockaddr *)&this->addr, sizeof(this->addr))<0) {
		perror("bind");
		this->status = -3;
		return;
	}

	if(listen(this->sockMaster, 3) < 0) {
		perror("listen\n");
		this->status = -4;
		return;
	}
}

static int doGetMessage(Socket *this) {
	int activity, valread;
	char message[] = "Pirei";


	int loop, loop2, new_sock;

	FD_ZERO(&this->readfds);
	/* reason we say max_clients+3 is stdin,stdout,stderr take up the first 
	 * couple of descriptors and we might as well allow a couple of extra.
	 * If your program opens files at all you will want to allow enough extra.
	 * Another option is to specify the maximum your operating system allows.
	 */

	/* setup which sockets to listen on */
	FD_SET(this->sockMaster, &this->readfds);

	for (loop = 0; loop < this->maxClients; loop++) {
		if(this->sockClient[loop] > 0)
			FD_SET(this->sockClient[loop], &this->readfds);
	}

	this->timeout.tv_sec = 0;
	this->timeout.tv_usec = 100;

	/* wait for connection, forever if we have to */
	activity = select(this->maxClients + 3, &this->readfds, NULL, NULL, &this->timeout);


	if((activity < 0) && (errno!=EINTR)) {
	/* there was an error with select() */
		D("no selecting\n");
	}
	D("selected\n");

	FD_ISSET(this->sockMaster, &this->readfds);
	D("%s\n", strerror(errno));
	if(FD_ISSET(this->sockMaster, &this->readfds)) {
		/* Open the new socket as 'new_socket' */
		D("Pirei\n");
		int len = sizeof(this->addr);

		if ((new_sock = accept(this->sockMaster, (struct sockaddr *) &this->addr, &len))<0)
		{
			/* if accept failed to return a socket descriptor, display error and exit */
				perror("accept");
				exit(EXIT_FAILURE);
		}
		/* inform user of socket number - used in send and receive commands */
		printf("New socket is fd %d\n",new_sock);
		if (send(new_sock, message, strlen(message), 0) != strlen(message)) {
		/* if send failed to send all the message, display error and exit */
			perror("send");
		}

		puts("Welcome message sent successfully");
		/* add new socket to list of sockets */
		for (loop = 0; loop < this->maxClients; loop++) {
			if (this->sockClient[loop] == 0) {
				this->sockClient[loop] = new_sock;
				printf("Adding to list of sockets as %d\n", loop);
				loop = this->maxClients;
			}
		}
	}

	for (loop = 0; loop < this->maxClients; loop++) {
		if (FD_ISSET(this->sockClient[loop], &this->readfds)) {
			if ((valread = read(this->sockClient[loop], this->buffer, 2048)) < 0) {
				close(this->sockClient[loop]);
				this->sockClient[loop] = 0;
			}
			else {
				/* set the terminating NULL byte on the end of the data read */
				this->buffer[valread] = 0;
				for (loop2 = 0; loop2 < this->maxClients; loop2++) {
					/* note, flags for send() are normally 0, see man page for details */
					send(this->sockClient[loop2], this->buffer, strlen(this->buffer), 0);
				}
			}
			/* 
			* use read() to read from the socket into a buffer using something
			* similar to the following:
			*
			* If the read didn't cause an error then send buffer to all 
			* client sockets in the array - use for loop and send() just
			* as if you were sending it to one connection
			*
			* important point to note is that if the connection is char-by-char
			* the person will not be able to send a complete string and you will
			* need to use buffers for each connection, checking for overflows and
			* new line characters (\n or \r)
			*/
		}
	}

	// D("Heh\n");

}


